package goods

import (
	"github.com/gin-gonic/gin"
	uuid "github.com/satori/go.uuid"
	"go.mongodb.org/mongo-driver/bson"
	"higame/config"
	"higame/modules/log"
	"higame/modules/store"
	"higame/modules/utils"
	log2 "higame/routes/log"
	"higame/routes/order"
	"higame/routes/user"
	"net/http"
)

func create(ctx *gin.Context) {
	v, err := validatorTrade(ctx)
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"code": http.StatusBadRequest,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}

	if err = AddOne(&Schema{
		GoodsID:   uuid.NewV1().String(),
		AddTime:   utils.Timestamp(),
		Title:     v.Title,
		Subtitle:  v.Subtitle,
		Price:     v.Price,
		MainImage: v.MainImage,
		Quantity:  v.Quantity,
		SourceUrl: v.SourceUrl,
		Sales:     v.Sales,
	}); err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": http.StatusInternalServerError,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"msg":  "添加成功！",
		"data": nil,
	})
}

func delete(ctx *gin.Context) {
	goodsId := ctx.PostForm("goods_id")
	err := DeleteOneByGoodsID(goodsId)

	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"code": http.StatusBadRequest,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}
	ctx.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"msg":  "删除成功",
		"data": nil,
	})
}

func update(ctx *gin.Context) {
	v, err := validatorTrade(ctx)
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"code": http.StatusBadRequest,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}
	if err = UpdateOneByGoodsID(v.GoodsID, bson.M{
		"title":      v.Title,
		"subtitle":   v.Subtitle,
		"price":      v.Price,
		"main_image": v.MainImage,
		"quantity":   v.Quantity,
		"source_url": v.SourceUrl,
		"sales":      v.Sales,
	}); err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": http.StatusInternalServerError,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"msg":  "修改成功！",
		"data": nil,
	})
}

func list(ctx *gin.Context) {
	pageNum := utils.StringToInt64(ctx.PostForm("page_num"), 1)
	list, _ := FindMany(pageNum, bson.M{})
	count, _ := Count(bson.M{})
	var str string = ""
	if count == 0 {
		str = "没有查询到数据！"
	} else {
		str = utils.JoinString("共%v页%v行 当前在第%v页", count/20+1, count, pageNum+1)
	}
	ctx.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"msg":  str,
		"data": gin.H{
			"list":  list,
			"total": count,
		},
	})
}

func buy(ctx *gin.Context) {
	goodsId := ctx.PostForm("goods_id")
	addressId := ctx.PostForm("address_id")
	quantity := utils.StringToInt64(ctx.PostForm("quantity"), 0)
	if goodsId == "" || addressId == "" || quantity <= 0 {
		ctx.JSON(400, gin.H{
			"code": 400,
			"msg":  "参数出错",
			"data": nil,
		})
		return
	}

	//获取当前登录的用户资料
	userItem := user.New()
	if u, err := store.GetClaims(ctx); err != nil {
		log.Error.Println(err)
		ctx.JSON(500, gin.H{
			"code": 500,
			"msg":  "服务器内部出错",
			"data": nil,
		})
		return
	} else if userItem, err = user.FindOneByName(u.Audience); err != nil {
		ctx.JSON(400, gin.H{
			"code": 400,
			"msg":  "当前你要购买的商品不存在",
			"data": nil,
		})
		return
	}

	// 获取用户地址
	addressItem, err := getAddress(userItem, addressId)
	if err != nil {
		ctx.JSON(400, gin.H{
			"code": 400,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}

	// 获取商品资料
	goodsItem, err := FindOneByGoodsID(goodsId)
	if err != nil {
		ctx.JSON(400, gin.H{
			"code": 400,
			"msg":  "当前你要购买的商品不存在",
			"data": nil,
		})
		return
	}

	// 检测余额
	if float64(userItem.Integral) < goodsItem.Price*float64(quantity) {
		ctx.JSON(400, gin.H{
			"code": 400,
			"msg":  "您没有足够的积分来兑换此商品",
			"data": nil,
		})
		return
	}

	// 创建订单
	if err := order.AddOne(&order.Schema{
		Seller:      config.AdminNick,
		Buyer:       userItem.Username,
		Quantity:    quantity,
		OrderID:     uuid.NewV1().String(),
		AddTime:     utils.Timestamp(),
		FHTime:      0,
		SHTime:      0,
		QXTime:      0,
		GoodsID:     goodsItem.GoodsID,
		Title:       goodsItem.Title,
		MainImage:   goodsItem.MainImage,
		Price:       goodsItem.Price,
		SourceUrl:   goodsItem.SourceUrl,
		OrderStatus: order.FK,
		Receiver:    addressItem,
		PayType:     order.IntegralPay,
		ExpressType: order.Express{},
		OrderType:   order.Goods,
	}); err != nil {
		log.Error.Println(err)
		ctx.JSON(500, gin.H{
			"code": 500,
			"msg":  "服务器内部出错",
			"data": nil,
		})
		return
	}

	// 修改用户积分
	if err := user.UpdateOne(bson.M{
		"username": userItem.Username,
	}, bson.M{
		"$inc": bson.M{
			"integral": 0 - int64(goodsItem.Price)*quantity,
		},
	}); err != nil {
		log.Error.Println(err)
		ctx.JSON(500, gin.H{
			"code": 500,
			"msg":  "服务器内部出错",
			"data": nil,
		})
		return
	}

	// 添加积分日志
	if err := log2.AddOneIntegralLog(&log2.IntegralLogSchema{
		UUID:     uuid.NewV1().String(),
		AddTime:  utils.Timestamp(),
		Username: userItem.Username,
		Integral: 0 - int64(goodsItem.Price)*quantity,
		Text:     "积分兑换商品",
		Other:    utils.JoinString("%v x %v", goodsItem.Title, quantity),
	}); err != nil {
		log.Error.Println(err)
		ctx.JSON(500, gin.H{
			"code": 500,
			"msg":  "服务器内部出错",
			"data": nil,
		})
		return
	}

	// 库存操作，这边有一个问题就是并发购买是否会同时操作库存
	// 我这里暂时不做相应的处理
	if err := UpdateOne(bson.M{"goods_id": goodsId}, bson.M{
		"$inc": bson.M{
			"quantity": 0 - quantity,
		},
	}); err != nil {
		ctx.JSON(400, gin.H{
			"code": 400,
			"msg":  "修改库存失败",
			"data": nil,
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"msg":  "支付成功，等待发货！",
		"data": nil,
	})
}
